<html>
  
  <head>
    <title>在线JSON Schema 生成默认模板</title>
	 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.9/ace.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.9/mode-json.js"></script>
    <script >
      (function () {
  function isPlainObject(obj) {
    return obj ? typeof obj === 'object' && Object.getPrototypeOf(obj) === Object.prototype : false;
  }

  const supportType = ['string', 'number', 'array', 'object', 'boolean', 'integer'];

  function getType(type, schema) {
    console.log(type)
    if (supportType.indexOf(type) !== -1) {
      return type;
    }
    return typeof type;
  }

  function isSchema(object) {
    if (supportType.indexOf(object.type) !== -1) {
      return true;
    }
    return false;
  }

  function handleSchema(key, json, schema) {
    Object.assign(schema, json);
    if (schema.type === 'object') {
      delete schema.properties;
      parse(key, json.properties, schema);
    }
    if (schema.type === 'array') {
      delete schema.items;
      schema.items = {};
      parse(key, json.items, schema.items)
    }

  }

  function handleArray(key,arr, schema) {
    schema.type = 'array';
    var props = schema.items = {};
    parse(key, arr[0], props)
  }

  function handleObject(key, json, schema) {
    if (isSchema(json)) {
      return handleSchema(key, json, schema)
    }
    schema.type = 'object';

    for (var key in json) {
      if (key[0] === '*') {
           schema.required = [];
           break;
      }
    }

    var props = schema.properties = {};
    for (var key in json) {
      var item = json[key];
      var curSchema = props[key] = {};

      if (key[0] === '*' || key[1] === '*' || key[0] === '&' || key[1] === '&') {
        if((key[0] === '*' || key[1] === '*') && (key[0] === '&' || key[1] === '&')) {
          schema.required.push(key.substr(2));
          curSchema = props[key.substr(2)] = {};
          delete props[key];
          if(key[0] === '*') {
             key = key.substr(1);
          } else {
            key1 = key.substr(0,1);
            key2 = key.substr(2);
            key = key1 + key2;
          } 
          // 只有& 的时候不添加required， 但是要截取第一个字符号
        } else if(key[0] === '*' ){
          delete props[key];
          key = key.substr(1);
          schema.required.push(key);
          curSchema = props[key] = {};
        } else if(key[0] === '&' ){
          delete props[key];
          curSchema = props[key.substr(1)] = {};
        } 
       
      }
      parse(key, item, curSchema)
    }
  }

  function parse(key, json, schema) {
    console.log("json = " ,json);
    if (Array.isArray(json)) {
      handleArray(key, json, schema);
    } else if (isPlainObject(json)) {
      handleObject(key, json, schema);
    }else   if (json === "0") {
      console.log("json =" ,json);
      schema.type = "string";
    }else   if (json === "") {
      console.log("json =" ,json);
      schema.type = "string";
    }
    else   if (json == 0) {
      console.log("json =" ,json);
      schema.type = "number";
    }else   if (!json) {
      console.log("null  不处理schema=" ,json);
    } else {
      if (key[0] === '&' || key[1] === '&') {
        if(key[0] === '&') {
            schema.enum = [];
           schema.enum.push(json);
        } else if(key[1] === '&'){
           schema.enum = [];
           schema.enum.push(json);
        }
      }
      schema.type = getType(json, schema);
    }
  }

  function ejs(data) {
    var JsonSchema = {};
    parse("$", data, JsonSchema);
    return JsonSchema;
  }

  if(typeof module !== 'undefined' && typeof module === 'object' && module.exports !== 'undefined'){
    module.exports = ejs;
  }

  if(typeof window !== 'undefined' && typeof window === 'object'){
    window.easyJsonSchema = ejs;
  }
  
})()
    </script>
    <style>
      .run{
        width: 180px;
        height: 35px;
        margin: 20px;
        background: #ebf45d;
      }
      .textarea{
        display: inline-block;
        width: 500px;
        height: 1200px;
      }
    </style>
  </head>

  <body>
    <button class="run" id="run">点击生成JSON Schema</button>
    <select id="select">
      <option>TestJSON1</option>
      <option>TestJSON2</option>
    </select>
	<a href = "https://www.jsonschemavalidator.net" target="_blank">Schema 验证工具   .</a>
  <a href = "https://www.bejson.com/?_t_t_t=0.09731022943742573" target="_blank">JSON格式化转化工具   .</a>
  <a href = "https://www.sojson.com/jsondiff.html" target="_blank">JSONDiff工具   .</a>
   <a href="https://dengkunnanmayun.gitee.io/conan-docs/#/use/README" target="_blank">柯南线上流量回平台放开源了</a></br>
	<label>在字段前加*表示该key为必要参数  </label>
  <label>在叶子节点前加&表示该vluae为全值校验 </label>
   <label>*&不需要关注顺序 </label>
   
    <div>
      <div class="textarea" id="text-area1"></div>
      <div readonly class="textarea" id="text-area2"></div>
    </div>

    <script>  
      var demoData = {
        TestJSON1: {
  "&id": "conanid",
  "name": "conan",
  "*email": "conan@xxx.com",
  "phoneNumber": 12306,
  "array": [{
    "*site": "string",
    "url": "string"
  }]
},

        TestJSON2: {
            "*id": "123",
            "*name": {
              "type": "conan2",
              "enum": [
                "tom",
                "jay"
              ],
              "minLength": 1,
              "maxLength": 10
            },
            "*images": [
              {
                "*id": "number",
                "names": {
                  "type": "array",
                  "title": "Images Collections.",
                  "items": {
                    "*id": "string",
                    "*name": "string"
                  }
                }
              }
            ],
            "abc": {
              "a": {
                "x": "string",
                "y": {
                  "type": "number",
                  "minimum": 400000,
                  "maximum": 900000
                }
              }
            }
          }
      }
    
      function loadEditor(container, readonly){
        var editor = ace.edit(container);
        editor.getSession().setMode("ace/mode/json");
        if(readonly){
          editor.setReadOnly(true)
          editor.renderer.$cursorLayer.element.style.display = "none"
        }
        return editor;
      }

      var editor1 = loadEditor("text-area1");
      editor1.setValue(JSON.stringify(demoData.TestJSON1, null, 2));
      editor1.clearSelection();
      var editor2 = loadEditor("text-area2");

      function run(){
        var text1 = editor1.getValue();
        var json;
        try{
          json = JSON.parse(text1);
          var result = easyJsonSchema(json);
          result = JSON.stringify(result, null, 2);
          editor2.setValue(result);
        }catch(err){
          alert('Json format is error.')
        }
      }

      document.getElementById('select').onchange = function(){
        editor1.setValue(JSON.stringify(demoData[this.value], null, 2));
        editor1.clearSelection();
        run();
      }

      run();

      document.getElementById('run').onclick = run;

    </script>
  </body>
</html>
